 //          * * * * * * * * * * * * *
    //          * *      WARNING      * *
    //          * * * * * * * * * * * * *
    // I wrote this alongside someone who happened to be:
    //
    //   a) Eager and ambitious at the beginning of their
    //      Programmer's Journey, and:
    //   b) Really keen on Pokémon.
    //
    // It was fun *training*, but the code's *evolution*
    // left it smelling somewhat like *Weezing* (these
    // are Pokemon things iirc, C_y I'm not hip anymore).
    //
    // Enter at your own risk, enjoy, catch 'em all :)
    // - rileyjshaw

    const colors = [
    '#f14713', // Standard ball
    '#eb43eb', // Master ball
    '#1aafff', // Great ball
    '#00dd7a', // Safari ball
    '#ff84ed', // Ultra ball
    ];

    // Editable.
    const d = 72;   // Diameter.
    const w = 8;    // Inner line width.
    const T = 120;  // Period, in frames @ 60fps.

    // Computed.
    const r = d/2;      // Radius.
    const r2_max = r/5; // Max radius of the mid-section.
    const l = r*2 + w;  // Canvas side length.

    // Constants.
    const {abs, PI: pi} = Math;
    const C_y = 4/3; // Simplified from 4/3*tan(θ/4)), since θ=π.
    const {body} = document;

    const bag = document.createElement('div');
    bag.setAttribute('id','loading')
    Object.assign(bag.style, {
    left: '50%',
    position: 'absolute',
    top: '50%',
    transform: 'translate3d(-50%, -50%, 0)',
});

    const team = colors.map(pokeball);
    team.forEach(ball => bag.appendChild(ball.canvas));
    // body.style.background = '#de73cd';
    body.appendChild(bag);

    !function loop (t) {
    team.forEach(({step}, i, {length}) => step((t + i*T/length) % T));
    requestAnimationFrame(loop.bind(this, t+1));
}(0);

    function pokeball (top) {
    // Constants.
    const canvas = document.createElement('canvas');
    const ctx = canvas.getContext('2d');

    // Prepare the canvas and clip it to a circle.
    canvas.width = canvas.height = l;
    Object.assign(canvas.style, {
    background: '#f0f0f0',
    border: `${w/2}px solid #f8f8f8`,
    borderRadius: '50%',
    boxShadow: '2px 4px rgba(34, 34, 36, 0.2)',
    height: `${l/2}px`,
    margin: `${w}px`,
    width: `${l/2}px`,
});
    ctx.translate(w/2, w/2);
    ctx.beginPath();
    ctx.lineWidth = w;
    ctx.arc(r, r, r, 0, 2*pi);
    ctx.stroke();
    ctx.clip();

    ctx.strokeStyle = '#222224';
    function step (t) {
    // t:     0 -------- T/2 -------- T
    // frame: 0 --------- T --------- 0
    // y:     bottom --- top --- bottom
    //     where bottom: 1 - C_y, top: C_y
    const frame = 2*(T/2 - abs(T/2 - t))
    const y = 1-C_y + frame/T*(2*C_y - 1);

    ctx.clearRect(0, 0, d, d);
    ctx.lineWidth = w;

    // Draw a "circle".
    ctx.beginPath();
    ctx.fillStyle = top;
    ctx.moveTo(-w/2, r);
    ctx.bezierCurveTo(-w/2, y*d, d+w, y*d, d+w, r);
    ctx.stroke();
    //ctx.arc(r, r, r, 0, pi, true);
    ctx.lineTo(d, 0);
    ctx.lineTo(0, 0);
    ctx.fill();
    ctx.closePath();

    // Draw the center circle.
    let c = d*y/C_y+r2_max*C_y;
    let r2 = r2_max*(1-abs(1/2-y)/3);
    let r3 = r2/3*2;

    ctx.beginPath();
    ctx.lineWidth /= 2;
    ctx.fillStyle = '#f0f0f0';
    ctx.arc(r, c, r2, 0, 2*pi);
    ctx.fill();
    ctx.stroke();
    ctx.closePath();

    ctx.beginPath();
    ctx.lineWidth /= 2;
    ctx.arc(r, c, r3, 0, 2*pi);
    ctx.stroke();
    ctx.closePath();
};
    return {canvas, step};
}
